package com.tre.jdevtemplateboot.aop;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.tre.jdevtemplateboot.common.util.JsonUtils;
import com.tre.jdevtemplateboot.exception.business.SysParamValidatorException;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

/**
 * @author JDev
 */
@Aspect
@Component
@Order(2)
public class OperatorLogToFileAspect {

    private final Logger logger = LoggerFactory.getLogger(getClass());
    private static final String EXCLUDE_LOGIN_CLASS = "Login";
    private static final String EXCLUDE_OAUTH_CLASS = "OAuth";
    ThreadLocal<Long> startTime = new ThreadLocal<>();
    @Value("${com.tre.logger.operator.request:true}")
    private Boolean operatorRequest;
    @Value("${com.tre.logger.operator.response:false}")
    private Boolean operatorResponse;

    @Pointcut("execution(public * com..*.web.controller..*.*(..))")
    private void controllerAspect() {
        throw new SysParamValidatorException();
    }

    @Before(value = "controllerAspect()")
    public void methodBefore(JoinPoint joinPoint) {
        if (operatorRequest) {
            startTime.set(System.currentTimeMillis());
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (requestAttributes != null ){
                HttpServletRequest request = requestAttributes.getRequest();
                if (!joinPoint.getTarget().getClass().getName().contains(EXCLUDE_OAUTH_CLASS)
                        && !joinPoint.getTarget().getClass().getName().contains(EXCLUDE_LOGIN_CLASS)){
                    logger.info("REQUEST={Args: {},RequestURL: {} }", Arrays.toString(joinPoint.getArgs()),request.getRequestURL());
                }
            }
        }
    }

    @AfterReturning(returning = "o", pointcut = "controllerAspect()")
    public void methodAfterReturning(Object o) throws JsonProcessingException {
        if (operatorResponse) {
            if (startTime.get() != null){
                logger.info("RESPONSE={SpendTime: {} ,Response Contents: {}}", String.format("%s",System.currentTimeMillis() - startTime.get()), JsonUtils.objectToJson(o));
            }else {
                logger.info("RESPONSE={SpendTime: '' ,Response Contents: {}}", JsonUtils.objectToJson(o));
            }
        }
        if (startTime != null){
            startTime.remove();
        }
    }

}
